import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js';
import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';

class LightDemo {
    constructor() {
        this.scene = null;
        this.camera = null;
        this.renderer = null;
        this.controls = null;
        
        // 光源对象
        this.lights = {
            ambient: null,
            directional: null,
            point: null,
            spot: null,
            hemisphere: null,
            rectArea: null
        };
        
        // 辅助对象
        this.helpers = {
            directional: null,
            directionalShadow: null,
            point: null,
            spot: null,
            rectArea: null
        };
        
        // 场景对象
        this.objects = {
            ground: null,
            sphere: null,
            cube: null,
            cylinder: null,
            torus: null
        };
        
        this.init();
        this.setupControls();
        this.animate();
    }
    
    init() {
        // 初始化场景
        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color(0x222222);
        
        // 初始化相机
        const container = document.getElementById('scene-container');
        const width = container.clientWidth;
        const height = container.clientHeight;
        
        this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
        this.camera.position.set(15, 15, 15);
        
        // 初始化渲染器
        this.renderer = new THREE.WebGLRenderer({ antialias: true });
        this.renderer.setSize(width, height);
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.outputColorSpace = THREE.SRGBColorSpace;
        
        container.appendChild(this.renderer.domElement);
        
        // 初始化控制器
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.enableDamping = true;
        this.controls.dampingFactor = 0.05;
        
        // 初始化RectAreaLight支持
        RectAreaLightUniformsLib.init();
        
        // 创建场景对象
        this.createObjects();
        
        // 创建光源
        this.createLights();
        
        // 添加坐标轴辅助器
        const axesHelper = new THREE.AxesHelper(5);
        this.scene.add(axesHelper);
        
        // 窗口大小调整
        window.addEventListener('resize', () => this.onWindowResize());
    }
    
    createObjects() {
        // 地面
        const groundGeometry = new THREE.PlaneGeometry(30, 30);
        const groundMaterial = new THREE.MeshLambertMaterial({ 
            color: 0x888888,
            side: THREE.DoubleSide
        });
        this.objects.ground = new THREE.Mesh(groundGeometry, groundMaterial);
        this.objects.ground.rotation.x = -Math.PI / 2;
        this.objects.ground.position.y = -2;
        this.objects.ground.receiveShadow = true;
        this.scene.add(this.objects.ground);
        
        // 球体
        const sphereGeometry = new THREE.SphereGeometry(1.5, 32, 32);
        const sphereMaterial = new THREE.MeshPhongMaterial({ 
            color: 0xff6b6b,
            shininess: 100
        });
        this.objects.sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        this.objects.sphere.position.set(-4, 1, -4);
        this.objects.sphere.castShadow = true;
        this.objects.sphere.receiveShadow = true;
        this.scene.add(this.objects.sphere);
        
        // 立方体
        const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);
        const cubeMaterial = new THREE.MeshPhongMaterial({ 
            color: 0x4ecdc4,
            shininess: 100
        });
        this.objects.cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        this.objects.cube.position.set(4, 1, -4);
        this.objects.cube.castShadow = true;
        this.objects.cube.receiveShadow = true;
        this.scene.add(this.objects.cube);
        
        // 圆柱体
        const cylinderGeometry = new THREE.CylinderGeometry(1, 1, 3, 32);
        const cylinderMaterial = new THREE.MeshPhongMaterial({ 
            color: 0xffe66d,
            shininess: 100
        });
        this.objects.cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
        this.objects.cylinder.position.set(-4, 1.5, 4);
        this.objects.cylinder.castShadow = true;
        this.objects.cylinder.receiveShadow = true;
        this.scene.add(this.objects.cylinder);
        
        // 环形
        const torusGeometry = new THREE.TorusGeometry(1.5, 0.5, 16, 100);
        const torusMaterial = new THREE.MeshPhongMaterial({ 
            color: 0xa8e6cf,
            shininess: 100
        });
        this.objects.torus = new THREE.Mesh(torusGeometry, torusMaterial);
        this.objects.torus.position.set(4, 1, 4);
        this.objects.torus.castShadow = true;
        this.objects.torus.receiveShadow = true;
        this.scene.add(this.objects.torus);
    }
    
    createLights() {
        // 环境光
        this.lights.ambient = new THREE.AmbientLight(0x404040, 0.4);
        this.scene.add(this.lights.ambient);
        
        // 方向光
        this.lights.directional = new THREE.DirectionalLight(0xffffff, 1);
        this.lights.directional.position.set(10, 10, 5);
        this.lights.directional.castShadow = true;
        this.lights.directional.shadow.mapSize.width = 2048;
        this.lights.directional.shadow.mapSize.height = 2048;
        this.lights.directional.shadow.camera.near = 0.5;
        this.lights.directional.shadow.camera.far = 50;
        this.lights.directional.shadow.camera.left = -15;
        this.lights.directional.shadow.camera.right = 15;
        this.lights.directional.shadow.camera.top = 15;
        this.lights.directional.shadow.camera.bottom = -15;
        this.scene.add(this.lights.directional);
        
        // 方向光辅助器
        this.helpers.directional = new THREE.DirectionalLightHelper(this.lights.directional, 2);
        this.helpers.directional.castShadow = false;
        this.scene.add(this.helpers.directional);
        
        // 方向光阴影相机辅助器
        this.helpers.directionalShadow = new THREE.CameraHelper(this.lights.directional.shadow.camera);
        this.helpers.directionalShadow.castShadow = false;
        this.scene.add(this.helpers.directionalShadow);
        
        // 点光源
        this.lights.point = new THREE.PointLight(0xff4444, 1, 20);
        this.lights.point.position.set(-8, 6, -8);
        this.lights.point.castShadow = true;
        this.lights.point.shadow.mapSize.width = 1024;
        this.lights.point.shadow.mapSize.height = 1024;
        this.scene.add(this.lights.point);
        
        // 点光源辅助器
        this.helpers.point = new THREE.PointLightHelper(this.lights.point, 0.5);
        this.helpers.point.castShadow = false;
        this.scene.add(this.helpers.point);
        
        // 聚光灯
        this.lights.spot = new THREE.SpotLight(0x44ff44, 1, 30, Math.PI / 6, 0.5, 2);
        this.lights.spot.position.set(8, 8, 8);
        this.lights.spot.target.position.set(4, 0, 4);
        this.lights.spot.castShadow = true;
        this.lights.spot.shadow.mapSize.width = 1024;
        this.lights.spot.shadow.mapSize.height = 1024;
        this.scene.add(this.lights.spot);
        this.scene.add(this.lights.spot.target);
        
        // 聚光灯辅助器
        this.helpers.spot = new THREE.SpotLightHelper(this.lights.spot);
        this.helpers.spot.castShadow = false;
        this.scene.add(this.helpers.spot);
        
        // 半球光
        this.lights.hemisphere = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.6);
        this.lights.hemisphere.position.set(0, 10, 0);
        // 半球光没有内置的辅助器，我们可以创建一个简单的指示器
        
        // 矩形区域光
        this.lights.rectArea = new THREE.RectAreaLight(0x4444ff, 3, 4, 4);
        this.lights.rectArea.position.set(0, 8, -8);
        this.lights.rectArea.lookAt(0, 0, 0);
        
        // 矩形区域光辅助器
        this.helpers.rectArea = new RectAreaLightHelper(this.lights.rectArea);
        this.helpers.rectArea.castShadow = false;
        this.scene.add(this.helpers.rectArea);
    }
    
    setupControls() {
        // 环境光控制
        const ambientCheckbox = document.getElementById('ambientLight');
        const ambientColor = document.getElementById('ambientColor');
        const ambientIntensity = document.getElementById('ambientIntensity');
        
        ambientCheckbox.addEventListener('change', (e) => {
            this.lights.ambient.visible = e.target.checked;
        });
        
        ambientColor.addEventListener('input', (e) => {
            this.lights.ambient.color.setHex(parseInt(e.target.value.replace('#', '0x')));
        });
        
        ambientIntensity.addEventListener('input', (e) => {
            this.lights.ambient.intensity = parseFloat(e.target.value);
        });
        
        // 方向光控制
        const directionalCheckbox = document.getElementById('directionalLight');
        const directionalColor = document.getElementById('directionalColor');
        const directionalIntensity = document.getElementById('directionalIntensity');
        
        directionalCheckbox.addEventListener('change', (e) => {
            this.lights.directional.visible = e.target.checked;
            this.helpers.directional.visible = e.target.checked;
            this.helpers.directionalShadow.visible = e.target.checked;
        });
        
        directionalColor.addEventListener('input', (e) => {
            this.lights.directional.color.setHex(parseInt(e.target.value.replace('#', '0x')));
        });
        
        directionalIntensity.addEventListener('input', (e) => {
            this.lights.directional.intensity = parseFloat(e.target.value);
        });
        
        // 点光源控制
        const pointCheckbox = document.getElementById('pointLight');
        const pointColor = document.getElementById('pointColor');
        const pointIntensity = document.getElementById('pointIntensity');
        
        pointCheckbox.addEventListener('change', (e) => {
            this.lights.point.visible = e.target.checked;
            this.helpers.point.visible = e.target.checked;
        });
        
        pointColor.addEventListener('input', (e) => {
            this.lights.point.color.setHex(parseInt(e.target.value.replace('#', '0x')));
        });
        
        pointIntensity.addEventListener('input', (e) => {
            this.lights.point.intensity = parseFloat(e.target.value);
        });
        
        // 聚光灯控制
        const spotCheckbox = document.getElementById('spotLight');
        const spotColor = document.getElementById('spotColor');
        const spotIntensity = document.getElementById('spotIntensity');
        
        spotCheckbox.addEventListener('change', (e) => {
            this.lights.spot.visible = e.target.checked;
            this.helpers.spot.visible = e.target.checked;
        });
        
        spotColor.addEventListener('input', (e) => {
            this.lights.spot.color.setHex(parseInt(e.target.value.replace('#', '0x')));
        });
        
        spotIntensity.addEventListener('input', (e) => {
            this.lights.spot.intensity = parseFloat(e.target.value);
        });
        
        // 半球光控制
        const hemisphereCheckbox = document.getElementById('hemisphereLight');
        const hemisphereColorSky = document.getElementById('hemisphereColorSky');
        const hemisphereColorGround = document.getElementById('hemisphereColorGround');
        const hemisphereIntensity = document.getElementById('hemisphereIntensity');
        
        hemisphereCheckbox.addEventListener('change', (e) => {
            if (e.target.checked) {
                this.scene.add(this.lights.hemisphere);
            } else {
                this.scene.remove(this.lights.hemisphere);
            }
        });
        
        hemisphereColorSky.addEventListener('input', (e) => {
            this.lights.hemisphere.color.setHex(parseInt(e.target.value.replace('#', '0x')));
        });
        
        hemisphereColorGround.addEventListener('input', (e) => {
            this.lights.hemisphere.groundColor.setHex(parseInt(e.target.value.replace('#', '0x')));
        });
        
        hemisphereIntensity.addEventListener('input', (e) => {
            this.lights.hemisphere.intensity = parseFloat(e.target.value);
        });
        
        // 矩形区域光控制
        const rectAreaCheckbox = document.getElementById('rectAreaLight');
        const rectAreaColor = document.getElementById('rectAreaColor');
        const rectAreaIntensity = document.getElementById('rectAreaIntensity');
        
        rectAreaCheckbox.addEventListener('change', (e) => {
            if (e.target.checked) {
                this.scene.add(this.lights.rectArea);
                this.scene.add(this.helpers.rectArea);
            } else {
                this.scene.remove(this.lights.rectArea);
                this.scene.remove(this.helpers.rectArea);
            }
        });
        
        rectAreaColor.addEventListener('input', (e) => {
            this.lights.rectArea.color.setHex(parseInt(e.target.value.replace('#', '0x')));
        });
        
        rectAreaIntensity.addEventListener('input', (e) => {
            this.lights.rectArea.intensity = parseFloat(e.target.value);
        });
        
        // 辅助对象显示控制
        const showHelpers = document.getElementById('showHelpers');
        showHelpers.addEventListener('change', (e) => {
            Object.values(this.helpers).forEach(helper => {
                if (helper) helper.visible = e.target.checked;
            });
        });
        
        // 阴影控制
        const enableShadows = document.getElementById('enableShadows');
        enableShadows.addEventListener('change', (e) => {
            this.renderer.shadowMap.enabled = e.target.checked;
            
            // 更新所有对象的阴影设置
            Object.values(this.objects).forEach(obj => {
                console.log(obj)
                if (obj) {
                    // obj.castShadow = e.target.checked;
                    obj.receiveShadow = e.target.checked;
                }
            });
            
            // 更新光源的阴影设置
            // 方向光不产生阴影
            this.lights.directional.castShadow = false;
            this.lights.point.castShadow = e.target.checked;
            this.lights.spot.castShadow = e.target.checked;
        });
        
        // 重置按钮
        const resetButton = document.getElementById('resetLights');
        resetButton.addEventListener('click', () => {
            this.resetLights();
        });
    }
    
    resetLights() {
        // 重置所有控制器到默认值
        document.getElementById('ambientLight').checked = true;
        document.getElementById('ambientColor').value = '#404040';
        document.getElementById('ambientIntensity').value = '0.4';
        
        document.getElementById('directionalLight').checked = true;
        document.getElementById('directionalColor').value = '#ffffff';
        document.getElementById('directionalIntensity').value = '1';
        
        document.getElementById('pointLight').checked = true;
        document.getElementById('pointColor').value = '#ff4444';
        document.getElementById('pointIntensity').value = '1';
        
        document.getElementById('spotLight').checked = true;
        document.getElementById('spotColor').value = '#44ff44';
        document.getElementById('spotIntensity').value = '1';
        
        document.getElementById('hemisphereLight').checked = false;
        document.getElementById('hemisphereColorSky').value = '#87ceeb';
        document.getElementById('hemisphereColorGround').value = '#8b4513';
        document.getElementById('hemisphereIntensity').value = '0.6';
        
        document.getElementById('rectAreaLight').checked = false;
        document.getElementById('rectAreaColor').value = '#4444ff';
        document.getElementById('rectAreaIntensity').value = '3';
        
        document.getElementById('showHelpers').checked = true;
        document.getElementById('enableShadows').checked = true;
        
        // 触发所有事件来更新场景
        document.getElementById('ambientLight').dispatchEvent(new Event('change'));
        document.getElementById('directionalLight').dispatchEvent(new Event('change'));
        document.getElementById('pointLight').dispatchEvent(new Event('change'));
        document.getElementById('spotLight').dispatchEvent(new Event('change'));
        document.getElementById('hemisphereLight').dispatchEvent(new Event('change'));
        document.getElementById('rectAreaLight').dispatchEvent(new Event('change'));
        document.getElementById('showHelpers').dispatchEvent(new Event('change'));
        document.getElementById('enableShadows').dispatchEvent(new Event('change'));
        
        // 重置光源属性
        this.lights.ambient.color.setHex(0x404040);
        // this.lights.ambient.intensity = 0.4;
        
        this.lights.directional.color.setHex(0xffffff);
        this.lights.directional.intensity = 1;
        
        this.lights.point.color.setHex(0xff4444);
        this.lights.point.intensity = 1;
        
        this.lights.spot.color.setHex(0x44ff44);
        this.lights.spot.intensity = 1;
        
        this.lights.hemisphere.color.setHex(0x87ceeb);
        this.lights.hemisphere.groundColor.setHex(0x8b4513);
        this.lights.hemisphere.intensity = 0.6;
        
        this.lights.rectArea.color.setHex(0x4444ff);
        this.lights.rectArea.intensity = 3;
    }
    
    animate() {
        requestAnimationFrame(() => this.animate());
        
        // 旋转物体以展示光照效果
        const time = Date.now() * 0.001;
        
        this.objects.sphere.rotation.y = time * 0.5;
        this.objects.cube.rotation.x = time * 0.3;
        this.objects.cube.rotation.y = time * 0.5;
        this.objects.cylinder.rotation.y = time * 0.7;
        this.objects.torus.rotation.x = time * 0.4;
        this.objects.torus.rotation.y = time * 0.6;
        
        // 让点光源移动
        this.lights.point.position.x = Math.sin(time) * 8;
        this.lights.point.position.z = Math.cos(time) * 8;
        
        // 更新控制器
        this.controls.update();
        
        // 更新辅助器
        if (this.helpers.spot) this.helpers.spot.update();
        
        // 渲染场景
        this.renderer.render(this.scene, this.camera);
    }
    
    onWindowResize() {
        const container = document.getElementById('scene-container');
        const width = container.clientWidth;
        const height = container.clientHeight;
        
        this.camera.aspect = width / height;
        this.camera.updateProjectionMatrix();
        
        this.renderer.setSize(width, height);
    }
}

// 初始化应用
window.addEventListener('DOMContentLoaded', () => {
    new LightDemo();
});